<!doctype html>
<html lang="en">
<head>
    <title>Code coverage report for contracts/Raffle.sol</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="../prettify.css" />
    <link rel="stylesheet" href="../base.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type='text/css'>
        .coverage-summary .sorter {
            background-image: url(../sort-arrow-sprite.png);
        }
    </style>
</head>
<body>
<div class='wrapper'>
  <div class='pad1'>
    <h1>
      <a href="../index.html">all files</a> / <a href="index.html">contracts/</a> Raffle.sol
    </h1>
    <div class='clearfix'>
      <div class='fl pad1y space-right2'>
        <span class="strong">61.29% </span>
        <span class="quiet">Statements</span>
        <span class='fraction'>19/31</span>
      </div>
      <div class='fl pad1y space-right2'>
        <span class="strong">50% </span>
        <span class="quiet">Branches</span>
        <span class='fraction'>4/8</span>
      </div>
      <div class='fl pad1y space-right2'>
        <span class="strong">57.14% </span>
        <span class="quiet">Functions</span>
        <span class='fraction'>8/14</span>
      </div>
      <div class='fl pad1y space-right2'>
        <span class="strong">62.5% </span>
        <span class="quiet">Lines</span>
        <span class='fraction'>30/48</span>
      </div>
    </div>
  </div>
  <div class='status-line medium'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184</td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">9×</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// Raffle
&nbsp;
// 进入彩票 付投注的钱
&nbsp;
// 选择随机获胜者
&nbsp;
// 每隔多久选出获胜者 =&gt; 全自动的
&nbsp;
// chainlink Oracle =&gt;
&nbsp;
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
&nbsp;
import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import {AutomationCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol";
import "hardhat/console.sol";
&nbsp;
error Raffle_NotEnougnEntered();
error Raffle_TransferFailed();
error Raffle_NotOpen();
error Raffle__UpkeepNotNeeded(
    uint256 currentBalance,
    uint256 numPlayers,
    uint256 raffleState
);
&nbsp;
/**
    title： 一个抽奖的合约示例
    创建一个不可篡改的智能合约，提供给用户抽奖
    实现了 vrf chainlink v2 以及 chainlink keepers 
 */
contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface {
    enum RaffleState {
        OPEN,
        CALCULATING
    }
    // events
    event RaffleEnter(address indexed player);
    event RequestRaffleWinner(uint256 indexed requestId);
    event WinnerPicked(address indexed winnerPicked);
&nbsp;
    VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
    uint256 private immutable i_enterFee;
    uint64 private immutable i_subscriptionId;
    uint256 private immutable i_interval;
    bytes32 private immutable i_gasLane;
    uint32 private immutable i_callbackGasLimit;
&nbsp;
    uint256 private s_lastTimeStamp;
&nbsp;
    RaffleState private s_raffleState;
&nbsp;
    address payable[] private s_players;
    address private s_recentWinner;
&nbsp;
    uint16 public REQUEST_CONFIRMATIONS = 3;
    uint32 public NUM_WORDS = 2;
    // uint32 public callbackGasLimit = 100000;
&nbsp;
    constructor(
        address vrfCoordinatorV2,
        uint256 enterFee,
        bytes32 gaslane, // key hash
        uint64 subscriptionId,
        uint32 callbackGasLimit,
        uint256 interval
    ) VRFConsumerBaseV2(vrfCoordinatorV2) {
        i_subscriptionId = subscriptionId;
        i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
        i_enterFee = enterFee;
        s_raffleState = RaffleState.OPEN;
        s_lastTimeStamp = block.timestamp;
        i_interval = interval;
        i_gasLane = gaslane;
        i_callbackGasLimit = callbackGasLimit;
    }
&nbsp;
    function enterRaffle() public payable {
        if (msg.value &lt; i_enterFee) {
            revert Raffle_NotEnougnEntered();
        }
        <span class="missing-if-branch" title="if path not taken" >I</span>if (s_raffleState != RaffleState.OPEN) {
            revert Raffle_NotOpen();
        }
        s_players.push(payable(msg.sender));
&nbsp;
        emit RaffleEnter(msg.sender);
    }
&nbsp;
    function checkUpkeep(
        bytes memory /* checkData */
    )
        public
        view
        override
        returns (bool upkeepNeeded, bytes memory /* performData */)
    {
        bool isOpen = (RaffleState.OPEN == s_raffleState);
        bool timePassed = ((block.timestamp - s_lastTimeStamp) &lt; i_interval);
        bool hasPlayers = s_players.length &gt; 0;
        bool hasBalance = address(this).balance &gt; 0;
        console.log(timePassed, 'timePassed');
        console.log(isOpen, 'isOpen');
        console.log(hasBalance, 'hasBalance');
        console.log(hasPlayers, 'hasPlayers');
        upkeepNeeded = (timePassed &amp;&amp; isOpen &amp;&amp; hasBalance &amp;&amp; hasPlayers);
        return (upkeepNeeded, "0x0");
    }
&nbsp;
    function performUpkeep(bytes calldata /* performData */) external override {
        (bool upkeepNeeded, ) = checkUpkeep("");
        <span class="missing-if-branch" title="else path not taken" >E</span>if (!upkeepNeeded) {
            revert Raffle__UpkeepNotNeeded(
                address(this).balance,
                s_players.length,
                uint256(s_raffleState)
            );
        }
        s_raffleState = RaffleState.CALCULATING;
<span class="cstat-no" title="statement not covered" >        uint256 requestId = i_vrfCoordinator.requestRandomWords(</span>
            i_gasLane,
            i_subscriptionId,
            REQUEST_CONFIRMATIONS,
            i_callbackGasLimit,
            NUM_WORDS
        );
<span class="cstat-no" title="statement not covered" >        emit RequestRaffleWinner(requestId);</span>
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function fulfillRandomWords(</span>
        uint256 /* requestId */,
        uint256[] memory randomWords
    ) internal override {
<span class="cstat-no" title="statement not covered" >        uint256 indexOfWinner = randomWords[0] % s_players.length;</span>
<span class="cstat-no" title="statement not covered" >        address payable recentWinner = s_players[indexOfWinner];</span>
        s_recentWinner = recentWinner;
        s_players = new address payable[](0);
        s_lastTimeStamp = block.timestamp;
<span class="cstat-no" title="statement not covered" >        (bool success, ) = recentWinner.call{value: address(this).balance}("");</span>
<span class="cstat-no" title="statement not covered" >        if (!success) {</span>
            revert Raffle_TransferFailed();
        }
&nbsp;
<span class="cstat-no" title="statement not covered" >        emit WinnerPicked(recentWinner);</span>
    }
&nbsp;
    function getEnterFee() public view returns (uint256) {
        return i_enterFee;
    }
&nbsp;
    function getPlayer(uint256 index) public view returns (address) {
        return s_players[index];
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function getRecentWinner() public view returns (address) {</span>
<span class="cstat-no" title="statement not covered" >        return s_recentWinner;</span>
    }
&nbsp;
    function getRaffleState() public view returns (RaffleState) {
        return s_raffleState;
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function getNumWords() public view returns (uint256) {</span>
<span class="cstat-no" title="statement not covered" >        return NUM_WORDS;</span>
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function getNumberOfPlayers() public view returns (uint256) {</span>
<span class="cstat-no" title="statement not covered" >        return s_players.length;</span>
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function getLastTimeStamp() public view returns (uint256) {</span>
<span class="cstat-no" title="statement not covered" >        return s_lastTimeStamp;</span>
    }
&nbsp;
<span class="fstat-no" title="function not covered" >    function getRequestConfirmations() public view returns (uint256) {</span>
<span class="cstat-no" title="statement not covered" >        return REQUEST_CONFIRMATIONS;</span>
    }
&nbsp;
    function getInterval() public view returns (uint256) {
        return i_interval;
    }
}
&nbsp;</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
  Code coverage
  generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Tue Apr 29 2025 15:59:52 GMT+0800 (China Standard Time)
</div>
</div>
<script src="../prettify.js"></script>
<script>
window.onload = function () {
        if (typeof prettyPrint === 'function') {
            prettyPrint();
        }
};
</script>
<script src="../sorter.js"></script>
</body>
</html>
